package cn.rslee.uaas.server;

import java.io.IOException;
import java.net.UnknownHostException;
import java.util.Date;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import cn.rslee.uaas.entity.AccessLog;
import cn.rslee.uaas.service.AccessLogService;

/**
 * 描述：
 * 
 * <pre>HISTORY
 * ****************************************************************************
 *  ID   DATE                   PERSON          REASON
 *  1    2016年2月18日      rslee               Create
 * ****************************************************************************
 * </pre>
 * @author rslee
 * @since 1.0
 */
public class AccessFilter implements Filter {
	
	private String excludes;
	private String userSessionName;
	private String sysCode;
	private String[] suffixies;
	
	private AccessLogService saver;
	

	@Override
	public void destroy() {
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		
		saveLog((HttpServletRequest)request,(HttpServletResponse)response);
		chain.doFilter(request, response);
	}

	@Override
	public void init(FilterConfig config) throws ServletException {
		excludes = config.getInitParameter("excludes");
		userSessionName = config.getInitParameter("userSessionName");
		sysCode = config.getInitParameter("sysCode");
		
		if(excludes != null && excludes.trim().length() > 0){
			suffixies = excludes.split(" ");
		}		
		
		//初始化保存的实现类
		ServletContext context = config.getServletContext();  
        ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(context);  
        saver = (AccessLogService) ctx.getBean("accessLogService");
	}
	
	private void saveLog(HttpServletRequest request,HttpServletResponse response){
		String url = request.getRequestURL().toString();
		String uri = request.getRequestURI();
		String referrer =request.getHeader("Referer");
		
		
		if(!isExInclude(uri) && !url.equals(referrer)){ // 解决filter两次调用的问题
			String ua = request.getHeader("User-Agent");
			Object cusCode = request.getSession().getAttribute(userSessionName);
			String username = cusCode == null ? "guest": cusCode.toString();
			
			AccessLog al = new AccessLog(sysCode,ua,getRequestIp(request),getLocalIp(),url,uri,referrer,username,new Date());
			
			new LogSaver(al).start(); // 高并发的情况下面可以考虑使用连接池
		}
	}
	
	/**
	 * @return
	 * 功能描述: 获取登录人IP
	 */
	private String getRequestIp(HttpServletRequest request){
		
		String ip = request.getHeader("x-forwarded-for");
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
	        ip = request.getHeader("Proxy-Client-IP");
	    }
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
	        ip = request.getHeader("WL-Proxy-Client-IP");
	    }
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
	        ip = request.getRemoteAddr();
	    }
	    return ip.equals("0:0:0:0:0:0:0:1")?"127.0.0.1":ip;
	}
	
	/**
	 * @return
	 * 功能描述:获取本机IP
	 */
	private  String getLocalIp(){
		try {
			return java.net.InetAddress.getLocalHost().getHostAddress();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
		return "unkonwn";
	}
	
	private boolean isExInclude(String url){
		if(suffixies != null && suffixies.length >0){
			for(String s : suffixies){
				if(url.endsWith(s)){
					return true;
				}
			}
		}
		return false;
	}
	
	class LogSaver extends Thread implements Runnable{
		AccessLog log;
		public LogSaver(AccessLog log){
			this.log = log;
		}
		@Override
		public void run() {
			saver.save(log);
		}
	}

}
